#include "touch_interrupt.h"
#define		INT_CYCLES_PER_LCD_NTC_UPDATE	9766	// at 256uS interrupt interval this is every 2.5 seconds
#define		KNOB_DAMPING_FACTOR				5		// Bigger is less damping
//#define		KNOB_GAIN_FACTOR				250*2.5/65535	// Bigger is more change per stroke
#define		KNOB_GAIN_FACTOR				250*2.5
/****************************************************************************
*						Touch Pad Variables									*
*****************************************************************************/
uint8_t		Red_Pad						= NO;
uint8_t		Blue_Pad					= NO;
uint8_t		Green_Pad					= NO;
uint8_t		Yellow_Pad					= NO;

uint8_t		Red_Encountered				= NO;
uint8_t		Blue_Encountered			= NO;
uint8_t		Green_Encountered			= NO;
uint8_t		Yellow_Encountered			= NO;

uint16_t	Red_Duration				= 0;
uint16_t	Blue_Duration				= 0;
uint16_t	Green_Duration				= 0;
uint16_t	Yellow_Duration				= 0;
uint16_t	Idle_Duration				= 0;

uint8_t		First_Pad					= NOSENSOR;
uint8_t		Second_Pad					= NOSENSOR;
uint8_t		Third_Pad					= NOSENSOR;
uint8_t		Fourth_Pad					= NOSENSOR;

uint16_t	leaktime_red				= 0;
uint16_t	leaktime_blue				= 0;
uint16_t	leaktime_green				= 0;
uint16_t	leaktime_yellow				= 0;

uint16_t	fastest_red					= 0x0FFF;
uint16_t	fastest_blue				= 0x0FFF;
uint16_t	fastest_green				= 0x0FFF;
uint16_t	fastest_yellow				= 0x0FFF;

uint8_t		Sensor						= RED;			// Touch Sensor
uint8_t		Last_Sensor					= YELLOW;
uint16_t	Long_Swipe_Timer			= 0;
uint16_t	falltime 					= 0x0FFF;

uint8_t		Found_1st_Pad				= NO;
uint8_t		Found_2nd_Pad				= NO;
uint8_t		Found_3rd_Pad				= NO;
uint8_t		Found_4th_Pad				= NO;

uint8_t		Gesture						= NONE;
uint8_t		Gesture_Sense				= NONE;
uint8_t		Gesture_Size				= NONE;
uint8_t		Gesture_Speed				= NONE;
uint8_t		Ack_Gesture_Found			= YES;
uint8_t		Acquiring_Gesture			= NO;
uint8_t		Gesture_Complete			= YES;

double		knob_speed					= 0;
//uint8_t		DacValueUpToDate			= NO;
uint8_t		Direction					= UP;
uint16_t	time_to_update_LCD_CUR		= NO;
uint16_t	time_to_update_LCD_NTC		= NO;
uint16_t	time_to_update_USB			= NO;
uint16_t	Soft_USB_Timer				= 0;
uint16_t	Soft_LCD_NTC_Timer			= 0;
uint16_t	Soft_LCD_CUR_Timer			= 0;


/****************************************************************************
*			Routine for measuring the touch sensors							*
*****************************************************************************/
uint16_t Get_Sensor_Time (volatile uint8_t *the_port, volatile uint8_t *the_ddr, uint8_t the_sensor, volatile uint8_t *the_pin)
{	uint16_t delay	= 0;
	TCNT1			= 0;
	*the_ddr		&= ~the_sensor;			//	Set the DDR to input. Value was 1 so resistive pull up.
	*the_port		&= ~the_sensor;			//	Set the value to 0, pin is now completely open with only the external 10M.
	TCCR1B			 = (1 << CS11);			//	Start the timer.
	while (*the_pin & the_sensor)			//	Keep updating "delay" as long as the pin is high. Should add a timeout. TODO.
		delay		 = TCNT1;				//
	TCCR1B			 = 0;					//	Found the fall time (capacitance), halt the timer.
	*the_port		|= the_sensor;			//	Set the pin to high (resistive pull up).
	*the_ddr		|= the_sensor;			//	Set the direction to output (low impedance pull up).
	return delay;
}

/****************************************************************************
*	Interrupt Service Routine for Timer 0 256us-OVF tdiv = 1us/tick			*
*	This interrupt services the USB port and cycles through the touch		*
*	pad sensor.																*
*																			*
*	Each sensor pin is high coming in here. This routine picks the next 	*
*	sensor in line and sets its state to high Z. It also sets up the round	*
*	robin for the next cycle through to try the next sensor in line.		*
*	It has to be set high in a Grey code order to keep the pin from 		*
*	glitching low and causing an immediate interrupt. First it is changed	*
*	from low-Z hi to pull-up resistor mode with the DDR bit. Then with the 	*
*	"PORTx" bit it's set to pure hi Z.										*
*****************************************************************************/
ISR(TIMER0_OVF_vect)
{
	Soft_LCD_NTC_Timer++;
	if (Soft_LCD_NTC_Timer >= INT_CYCLES_PER_LCD_NTC_UPDATE)
	{	time_to_update_LCD_NTC = YES;
		Soft_LCD_NTC_Timer = 0;
	}

	if (Last_Sensor == RED)		{Sensor = BLUE;		falltime		= Get_Sensor_Time(&BLUE_PORT,	&BLUE_DDR,		BLUE_SENSOR, 	&BLUE_PIN);		}
	if (Last_Sensor == BLUE)	{Sensor = GREEN;	falltime		= Get_Sensor_Time(&GREEN_PORT,	&GREEN_DDR,		GREEN_SENSOR, 	&GREEN_PIN);	}
	if (Last_Sensor == GREEN)	{Sensor = YELLOW;	falltime		= Get_Sensor_Time(&YELLOW_PORT,	&YELLOW_DDR,	YELLOW_SENSOR,	&YELLOW_PIN);	}
	if (Last_Sensor == YELLOW)	{Sensor = RED;		falltime		= Get_Sensor_Time(&RED_PORT,	&RED_DDR,		RED_SENSOR, 	&RED_PIN);		}
//	if (Last_Sensor == YELLOW)	{Sensor = RED;		falltime		= REDPAD.get_time();}
	
	Last_Sensor = Sensor;

	leaktime_red++;
	leaktime_blue++;
	leaktime_green++;
	leaktime_yellow++;																					// Slow leakage timer
	
	if (Sensor == RED)		{if (falltime < fastest_red)						fastest_red--;			// Set falltime to min ever seen
							else if (leaktime_red > LEAKAGE_TIME )				{fastest_red++;			// Leaky integrator pulling up on fastest
																				leaktime_red = 0;}
																				
							if	(falltime > fastest_red + (fastest_red >> 3))
								{if (Red_Pad == NO)								Red_Pad = YES;}
							else if (Red_Pad == YES)							Red_Pad = NO;
							}
						
							
							
	else if (Sensor == BLUE)
							{if (falltime < fastest_blue)						fastest_blue--;			// Set falltime to min ever seen
							else if (leaktime_blue > LEAKAGE_TIME )				{fastest_blue++;		// Leaky integrator pulling up on fastest
																				leaktime_blue = 0;}
																				
							if	(falltime > fastest_blue  + (fastest_blue >> 3))
								{if (Blue_Pad == NO)							Blue_Pad = YES;}
							else if	(Blue_Pad == YES)							Blue_Pad = NO;
							}


							
	else if (Sensor == GREEN)
							{if (falltime < fastest_green)						fastest_green--;		// Set falltime to min ever seen
							else if (leaktime_green > LEAKAGE_TIME )			{fastest_green++;		// Leaky integrator pulling up on fastest
																				leaktime_green = 0;}
																				
							if	(falltime > fastest_green + (fastest_green >> 3))
								{if (Green_Pad == NO)							Green_Pad = YES;}
							else if (Green_Pad == YES)							Green_Pad = NO;
							}


							
	else if (Sensor == YELLOW)
							{if (falltime < fastest_yellow)						fastest_yellow--;		// Set falltime to min ever seen
							else if (leaktime_yellow > LEAKAGE_TIME )			{fastest_yellow++;		// Leaky integrator pulling up on fastest
																				leaktime_yellow = 0;}
																				
							if	(falltime > fastest_yellow + (fastest_yellow >> 3))
								{if (Yellow_Pad == NO)							Yellow_Pad = YES;}
							else if (Yellow_Pad == YES)							Yellow_Pad = NO;
							}
	
	
	if (Red_Pad == NO && Blue_Pad == NO && Green_Pad == NO && Yellow_Pad == NO)		Idle_Duration++;
	else																			Idle_Duration = 0;

	if (Red_Duration == 0xFFFF)				Red_Duration--;
	if (Blue_Duration == 0xFFFF)			Blue_Duration--;
	if (Green_Duration == 0xFFFF)			Green_Duration--;
	if (Yellow_Duration == 0xFFFF)			Yellow_Duration--;
	if (Idle_Duration == 0xFFFF)			Idle_Duration--;

	if (Long_Swipe_Timer > 0)
		{Long_Swipe_Timer++;
		Acquiring_Gesture = NO;
		}
	if (Long_Swipe_Timer > LONG_SWIPE_TIMEOUT)
		Long_Swipe_Timer = 0;

	if (Idle_Duration < MAX_IDLE_TIME && Acquiring_Gesture == NO && Ack_Gesture_Found == YES)			// Start of new gesture after 400ms idle
	{	Acquiring_Gesture = YES;
		Gesture_Complete = NO;
		Found_1st_Pad = NO;
		Found_2nd_Pad = NO;
		Found_3rd_Pad = NO;
		Found_4th_Pad = NO;
		Red_Duration = 0;
		Blue_Duration = 0;
		Green_Duration = 0;
		Yellow_Duration = 0;
		Red_Encountered = NO;
		Blue_Encountered = NO;
		Green_Encountered = NO;
		Yellow_Encountered = NO;
	}
	
	if (Acquiring_Gesture == YES)
	{	if (Red_Pad == YES)
		{	Red_Duration++;
			if(Found_1st_Pad == NO)										{First_Pad = RED;		Found_1st_Pad = YES;	Red_Encountered = YES;}
			if(Found_2nd_Pad == NO && Red_Encountered == NO)			{Second_Pad = RED;		Found_2nd_Pad = YES;	Red_Encountered = YES;}
			if(Found_3rd_Pad == NO && Red_Encountered == NO)			{Third_Pad = RED;		Found_3rd_Pad = YES;	Red_Encountered = YES;}
			if(Found_4th_Pad == NO && Red_Encountered == NO)			{Fourth_Pad = RED;		Found_4th_Pad = YES;}
		}
		if (Blue_Pad == YES)
		{	Blue_Duration++;
			if(Found_1st_Pad == NO)										{First_Pad = BLUE;		Found_1st_Pad = YES;	Blue_Encountered = YES;}
			if(Found_2nd_Pad == NO && Blue_Encountered == NO)			{Second_Pad = BLUE;		Found_2nd_Pad = YES;	Blue_Encountered = YES;}
			if(Found_3rd_Pad == NO && Blue_Encountered == NO)			{Third_Pad = BLUE;		Found_3rd_Pad = YES;	Blue_Encountered = YES;}
			if(Found_4th_Pad == NO && Blue_Encountered == NO)			{Fourth_Pad = BLUE;		Found_4th_Pad = YES;}
		}
		if (Green_Pad == YES)
		{	Green_Duration++;
			if(Found_1st_Pad == NO)										{First_Pad = GREEN;		Found_1st_Pad = YES;	Green_Encountered = YES;}
			if(Found_2nd_Pad == NO && Green_Encountered == NO)			{Second_Pad = GREEN;	Found_2nd_Pad = YES;	Green_Encountered = YES;}
			if(Found_3rd_Pad == NO && Green_Encountered == NO)			{Third_Pad = GREEN;		Found_3rd_Pad = YES;	Green_Encountered = YES;}
			if(Found_4th_Pad == NO && Green_Encountered == NO)			{Fourth_Pad = GREEN;	Found_4th_Pad = YES;}
		}
		if (Yellow_Pad == YES)
		{	Yellow_Duration++;
			if(Found_1st_Pad == NO)										{First_Pad = YELLOW;	Found_1st_Pad = YES;	Yellow_Encountered = YES;}
			if(Found_2nd_Pad == NO && Yellow_Encountered == NO)			{Second_Pad = YELLOW;	Found_2nd_Pad = YES;	Yellow_Encountered = YES;}
			if(Found_3rd_Pad == NO && Yellow_Encountered == NO)			{Third_Pad = YELLOW;	Found_3rd_Pad = YES;	Yellow_Encountered = YES;}
			if(Found_4th_Pad == NO && Yellow_Encountered == NO)			{Fourth_Pad = YELLOW;	Found_4th_Pad = YES;}
		}

		if (Found_1st_Pad && Found_2nd_Pad && Found_3rd_Pad && Found_4th_Pad && Gesture_Complete == NO)
		{	if (First_Pad == RED && Second_Pad == BLUE && Third_Pad == GREEN && Fourth_Pad == YELLOW)
			{	Gesture					= SWIPE;
				Gesture_Sense			= RIGHT;
				Gesture_Size			= LARGE;
				Gesture_Speed			= FAST;
				Ack_Gesture_Found		= NO;
				if (Red_Duration + Blue_Duration + Green_Duration + Yellow_Duration > FAST_TIME)				Gesture_Speed = INTERMEDIATE;
				if (Red_Duration + Blue_Duration + Green_Duration + Yellow_Duration > INTERMEDIATE_TIME)		Gesture_Speed = SLOW;
			}
			if (First_Pad == YELLOW && Second_Pad == GREEN && Third_Pad == BLUE && Fourth_Pad == RED)
			{	Gesture					= SWIPE;
				Gesture_Sense			= LEFT;
				Gesture_Size			= LARGE;
				Gesture_Speed			= FAST;
				Ack_Gesture_Found		= NO;
				if (Red_Duration + Blue_Duration + Green_Duration + Yellow_Duration > FAST_TIME)				Gesture_Speed = INTERMEDIATE;
				if (Red_Duration + Blue_Duration + Green_Duration + Yellow_Duration > INTERMEDIATE_TIME)		Gesture_Speed = SLOW;
			}
		Gesture_Complete = YES;
		Acquiring_Gesture = NO;
		Long_Swipe_Timer++;
		}

		if (Found_1st_Pad && Found_2nd_Pad && Gesture_Complete == NO)
			if ((First_Pad == RED && Second_Pad == YELLOW) || (First_Pad == YELLOW && Second_Pad == RED))
			{	Gesture				= DOUBLE_PAD;
				Gesture_Sense		= NONE;
				Gesture_Size		= NONE;
				Gesture_Speed		= VERY_SLOW;
				if ((Red_Duration > SLOW_TIME) && (Yellow_Duration > SLOW_TIME))
				{	Gesture_Complete = YES;
					Acquiring_Gesture = NO;
					Ack_Gesture_Found = NO;
				}
			}

		if (Idle_Duration >= MAX_IDLE_TIME && Gesture_Complete == NO)				// Need to make some decision here - time's up!
		
		{	Acquiring_Gesture = NO;
			if (Found_1st_Pad && Found_2nd_Pad && Found_3rd_Pad && Gesture_Complete == NO)
			{	if (First_Pad == RED && Second_Pad == BLUE && Third_Pad == GREEN)
				{	Gesture					= SWIPE;
					Gesture_Sense			= RIGHT;
					Gesture_Size			= MEDIUM;
					Gesture_Speed			= FAST;
					Ack_Gesture_Found		= NO;
					if (Red_Duration + Blue_Duration + Green_Duration > FAST_TIME)							Gesture_Speed = INTERMEDIATE;
					if (Red_Duration + Blue_Duration + Green_Duration > INTERMEDIATE_TIME)					Gesture_Speed = SLOW;
				}
				if (First_Pad == YELLOW && Second_Pad == GREEN && Third_Pad == BLUE)
				{	Gesture					= SWIPE;
					Gesture_Sense			= LEFT;
					Gesture_Size			= MEDIUM;
					Gesture_Speed			= FAST;
					Ack_Gesture_Found		= NO;
					if (Yellow_Duration + Green_Duration + Blue_Duration > FAST_TIME)							Gesture_Speed = INTERMEDIATE;
					if (Yellow_Duration + Green_Duration + Blue_Duration > INTERMEDIATE_TIME)					Gesture_Speed = SLOW;
				}
				if (First_Pad == BLUE && Second_Pad == GREEN && Third_Pad == YELLOW)
				{	Gesture					= SWIPE;
					Gesture_Sense			= RIGHT;
					Gesture_Size			= MEDIUM;
					Gesture_Speed			= FAST;
					Ack_Gesture_Found		= NO;
					if (Blue_Duration + Green_Duration + Yellow_Duration > FAST_TIME)							Gesture_Speed = INTERMEDIATE;
					if (Blue_Duration + Green_Duration + Yellow_Duration > INTERMEDIATE_TIME)					Gesture_Speed = SLOW;
				}
				if (First_Pad == GREEN && Second_Pad == BLUE && Third_Pad == RED)
				{	Gesture					= SWIPE;
					Gesture_Sense			= LEFT;
					Gesture_Size			= MEDIUM;
					Gesture_Speed			= FAST;
					Ack_Gesture_Found		= NO;
					if (Green_Duration + Blue_Duration + Red_Duration > FAST_TIME)								Gesture_Speed = INTERMEDIATE;
					if (Green_Duration + Blue_Duration + Red_Duration > INTERMEDIATE_TIME)						Gesture_Speed = SLOW;
				}
			Gesture_Complete = YES;
			}
			
			if (Found_1st_Pad && Found_2nd_Pad && Gesture_Complete == NO)
			{	if (First_Pad == RED && Second_Pad == BLUE)
				{	Gesture					= SWIPE;
					Gesture_Sense			= RIGHT;
					Gesture_Size			= SMALL;
					Gesture_Speed			= FAST;
					Ack_Gesture_Found		= NO;
					if (Red_Duration + Blue_Duration > FAST_TIME)												Gesture_Speed = INTERMEDIATE;
					if (Red_Duration + Blue_Duration > INTERMEDIATE_TIME)										Gesture_Speed = SLOW;
				}
				if (First_Pad == YELLOW && Second_Pad == GREEN)
				{	Gesture					= SWIPE;
					Gesture_Sense			= LEFT;
					Gesture_Size			= SMALL;
					Gesture_Speed			= FAST;
					Ack_Gesture_Found		= NO;
					if (Yellow_Duration + Green_Duration > FAST_TIME)											Gesture_Speed = INTERMEDIATE;
					if (Yellow_Duration + Green_Duration > INTERMEDIATE_TIME)									Gesture_Speed = SLOW;
				}
				
				if (First_Pad == GREEN && Second_Pad == BLUE)
				{	Gesture					= SWIPE;
					Gesture_Sense			= LEFT;
					Gesture_Size			= SMALL;
					Gesture_Speed			= FAST;
					Ack_Gesture_Found		= NO;
					if (Green_Duration + Blue_Duration > FAST_TIME)											Gesture_Speed = INTERMEDIATE;
					if (Green_Duration + Blue_Duration > INTERMEDIATE_TIME)									Gesture_Speed = SLOW;
				}
				
				if (First_Pad == BLUE && Second_Pad == RED)
				{	Gesture					= SWIPE;
					Gesture_Sense			= LEFT;
					Gesture_Size			= SMALL;
					Gesture_Speed			= FAST;
					Ack_Gesture_Found		= NO;
					if (Blue_Duration + Red_Duration > FAST_TIME)											Gesture_Speed = INTERMEDIATE;
					if (Blue_Duration + Red_Duration > INTERMEDIATE_TIME)									Gesture_Speed = SLOW;
				}
				
				if (First_Pad == BLUE && Second_Pad == GREEN)
				{	Gesture					= SWIPE;
					Gesture_Sense			= RIGHT;
					Gesture_Size			= SMALL;
					Gesture_Speed			= FAST;
					Ack_Gesture_Found		= NO;
					if (Blue_Duration + Green_Duration > FAST_TIME)											Gesture_Speed = INTERMEDIATE;
					if (Blue_Duration + Green_Duration > INTERMEDIATE_TIME)									Gesture_Speed = SLOW;
				}
				
				if (First_Pad == GREEN && Second_Pad == YELLOW)
				{	Gesture					= SWIPE;
					Gesture_Sense			= RIGHT;
					Gesture_Size			= SMALL;
					Gesture_Speed			= FAST;
					Ack_Gesture_Found		= NO;
					if (Green_Duration + Yellow_Duration > FAST_TIME)											Gesture_Speed = INTERMEDIATE;
					if (Green_Duration + Yellow_Duration > INTERMEDIATE_TIME)									Gesture_Speed = SLOW;
				}
			Gesture_Complete = YES;
			}
			
			if (Found_1st_Pad && Gesture_Complete == NO)
			{	if (First_Pad == RED)
				{	Gesture					= TOUCH;
					Gesture_Sense			= RED;
					Gesture_Size			= SMALL;
					Gesture_Speed			= FAST;
					Ack_Gesture_Found		= NO;
					if (Red_Duration > FAST_TIME)																Gesture_Speed = INTERMEDIATE;
					if (Red_Duration > INTERMEDIATE_TIME)														Gesture_Speed = SLOW;
				}
				if (First_Pad == BLUE)
				{	Gesture					= TOUCH;
					Gesture_Sense			= BLUE;
					Gesture_Size			= SMALL;
					Gesture_Speed			= FAST;
					Ack_Gesture_Found		= NO;
					if (Blue_Duration > FAST_TIME)																Gesture_Speed = INTERMEDIATE;
					if (Blue_Duration > INTERMEDIATE_TIME)														Gesture_Speed = SLOW;
				}
				if (First_Pad == GREEN)
				{	Gesture					= TOUCH;
					Gesture_Sense			= GREEN;
					Gesture_Size			= SMALL;
					Gesture_Speed			= FAST;
					Ack_Gesture_Found		= NO;
					if (Green_Duration > FAST_TIME)																Gesture_Speed = INTERMEDIATE;
					if (Green_Duration > INTERMEDIATE_TIME)														Gesture_Speed = SLOW;
				}
				if (First_Pad == YELLOW)
				{	Gesture					= TOUCH;
					Gesture_Sense			= YELLOW;
					Gesture_Size			= SMALL;
					Gesture_Speed			= FAST;
					Ack_Gesture_Found		= NO;
					if (Yellow_Duration > FAST_TIME)															Gesture_Speed = INTERMEDIATE;
					if (Yellow_Duration > INTERMEDIATE_TIME)													Gesture_Speed = SLOW;
				}
			Gesture_Complete = YES;
			}
		}
	}
}
/**************************************************************************
*  Respond to gesture command.                                            *
***************************************************************************/
void process_gesture(IO_pointers_t IO)
{
	static double old_knob_position = 0;
	double knob_position;
	knob_position = get_current_value(IO);
	int knob_change = 0;
	uint8_t range;
	range = get_range();
	
	if (Ack_Gesture_Found == NO)
	{	if (Gesture == SWIPE)
		{	if (Gesture_Sense == RIGHT)
			{	Direction = UP;
				if (Gesture_Size == SMALL	&&	Gesture_Speed == SLOW)				{knob_change += 1;}
				if (Gesture_Size == SMALL	&&	Gesture_Speed == INTERMEDIATE)		{knob_change += 1;}
				if (Gesture_Size == SMALL	&&	Gesture_Speed == FAST)				{knob_change += 4;}
				if (Gesture_Size == MEDIUM	&&	Gesture_Speed == SLOW)				{knob_change += 2;}
				if (Gesture_Size == MEDIUM	&&	Gesture_Speed == INTERMEDIATE)		{knob_change += 10;}
				if (Gesture_Size == MEDIUM	&&	Gesture_Speed == FAST)				{knob_change += 20;}
				if (Gesture_Size == LARGE	&&	Gesture_Speed == SLOW)				{knob_change += 4;}
				if (Gesture_Size == LARGE	&&	Gesture_Speed == INTERMEDIATE)		{knob_speed += 0.05;}
				if (Gesture_Size == LARGE	&&	Gesture_Speed == FAST)				{knob_speed += 1;}
				
			}
			else if (Gesture_Sense == LEFT)
			{	Direction = DOWN;
				if (Gesture_Size == SMALL	&&	Gesture_Speed == SLOW)				{knob_change -= 1;}
				if (Gesture_Size == SMALL	&&	Gesture_Speed == INTERMEDIATE)		{knob_change -= 1;}
				if (Gesture_Size == SMALL	&&	Gesture_Speed == FAST)				{knob_change -= 4;}
				if (Gesture_Size == MEDIUM	&&	Gesture_Speed == SLOW)				{knob_change -= 2;}
				if (Gesture_Size == MEDIUM	&&	Gesture_Speed == INTERMEDIATE)		{knob_change -= 10;}
				if (Gesture_Size == MEDIUM	&&	Gesture_Speed == FAST)				{knob_change -= 20;}
				if (Gesture_Size == LARGE	&&	Gesture_Speed == SLOW)				{knob_change -= 4;}
				if (Gesture_Size == LARGE	&&	Gesture_Speed == INTERMEDIATE)		{knob_speed += 0.05;}
				if (Gesture_Size == LARGE	&&	Gesture_Speed == FAST)				{knob_speed += 1;}
				
			}
		}
		if (knob_speed !=0 && Gesture == TOUCH)
			knob_speed = 0;				// Stop knob spinning on any tap
		
		if (knob_speed == 0 && Gesture == TOUCH)
		{
			if      ( Gesture_Sense == YELLOW )
				knob_change += 4;
			else if ( Gesture_Sense == GREEN )
				knob_change += 1;
			else if ( Gesture_Sense == BLUE )
				knob_change -= 1;
			else if ( Gesture_Sense == RED )
				knob_change -= 4;
		}
		Ack_Gesture_Found = YES;
	}
	
	if (range == HIGH)
		knob_position += knob_change * STEPSIZE_HI;
	else
		knob_position += knob_change * STEPSIZE_LO;
		
	if (knob_speed > 0)
	{
		if (Direction == UP)
		{	if(range == HIGH)
				knob_position += knob_speed * KNOB_GAIN_FACTOR * STEPSIZE_HI;
			else
				knob_position += knob_speed * KNOB_GAIN_FACTOR * STEPSIZE_LO;
		}
			
		else
		{	if(range == HIGH)
				knob_position -= knob_speed * KNOB_GAIN_FACTOR * STEPSIZE_HI;
			else
				knob_position -= knob_speed * KNOB_GAIN_FACTOR * STEPSIZE_LO;
		}
		
		
		knob_speed -= knob_speed / KNOB_DAMPING_FACTOR;
		if (knob_speed < 0.01)
			knob_speed = 0;
	}
	
	if (knob_position >= 2.6)
		knob_position  = 2.6;
	if (knob_position <= 0)
		knob_position  = 0;
	
	if (knob_position != old_knob_position)
		set_crnt_from_knob(knob_position, IO);
	old_knob_position = knob_position;

}
/**************************************************************************
*  Update LCD Display if time to                                          *
***************************************************************************/
void update_LCD(IO_pointers_t IO)
{
	if ( time_to_update_LCD_NTC )
	{
		update_LCD_temperature(IO);
		time_to_update_LCD_NTC = NO;
	}
}

